package org.sja.log2traffic;

import java.io.File;

import org.sja.log2traffic.dataStructures.CategoryTrackerEntity;
import org.sja.log2traffic.dataStructures.ConfigurationEntity;
import org.sja.log2traffic.dataStructures.CounterForDateAndResponseTimeEntity;
import org.sja.log2traffic.dataStructures.ILogData;
import org.sja.log2traffic.dataStructures.ProcessingStatusEntity;
import org.sja.log2traffic.dataStructures.simpleTime.LogDataSimpleTime;
import org.sja.log2traffic.dataStructures.timeAgregator.LogDataTimeAgregator;
import org.sja.log2traffic.outputers.GeneralStatisticToJSON;
import org.sja.log2traffic.outputers.MultipleAxisChartRenderer;


public class LogAnalyzerMain {

	private ConfigurationManipulator configurationManipulator;
	private IStatusOutputer statusOutputer;
	private LogAnalyzer logAnalyzer;
	private MultipleAxisChartRenderer multipleAxisChartRenderer;
	private GeneralStatisticToJSON generalStatisticToJSON;
	private ITimeAgregatorCalculator timeAgregatorCalculator;
	private ISimpleTimeCalculator simpleTimeCalculator;
	private IFileOperations fileOperations;

	public LogAnalyzerMain(ConfigurationManipulator configurationManipulator, IStatusOutputer statusOutputer, LogAnalyzer logAnalyzer, MultipleAxisChartRenderer multipleAxisChartRenderer, GeneralStatisticToJSON generalStatisticToJSON, ITimeAgregatorCalculator timeAgregatorCalculator,
			ISimpleTimeCalculator simpleTimeCalculator, IFileOperations fileOperations) {
		this.configurationManipulator = configurationManipulator;
		this.statusOutputer = statusOutputer;
		this.logAnalyzer = logAnalyzer;
		this.multipleAxisChartRenderer = multipleAxisChartRenderer;
		this.generalStatisticToJSON = generalStatisticToJSON;
		this.timeAgregatorCalculator = timeAgregatorCalculator;
		this.simpleTimeCalculator = simpleTimeCalculator;
		this.fileOperations = fileOperations;
	}

	public static void main(String[] args) {

		LogAnalyzerFactory.getInstance().provideLogAnalyzerMain().nonStaticMain(args);

	}

	private void nonStaticMain(String[] args) {

		String propertiesFilename = args[0];
		
		File configFile = new File(propertiesFilename);
		if (!(configFile.isFile())){
			throw new RuntimeException("File not exist: " + propertiesFilename);
		}
		
		System.out.println("Config file: " + configFile.getAbsolutePath());
		
		ConfigurationEntity configurationForMonths = configurationManipulator.getConfigurationForMonthsReport(propertiesFilename);
		ConfigurationEntity configurationForWeeks = configurationManipulator.getConfigurationForWeeksReport(propertiesFilename);
		ConfigurationEntity configurationForDays = configurationManipulator.getConfigurationForDaysReport(propertiesFilename);
		ConfigurationEntity configurationForHours = configurationManipulator.getConfigurationForHoursReport(propertiesFilename);
		fileOperations.deleteDirectory(configurationForMonths.getRootOutputConfigurationDirectory());
		
		ProcessingStatusEntity processingStatusEntity = new ProcessingStatusEntity(statusOutputer, configurationForMonths.getTrafficEnvironment());

		CategoryTrackerEntity categoryTrackerEntityMonths = new CategoryTrackerEntity();
		CategoryTrackerEntity categoryTrackerEntityWeeks = new CategoryTrackerEntity();
		CategoryTrackerEntity categoryTrackerEntityDays = new CategoryTrackerEntity();
		CategoryTrackerEntity categoryTrackerEntityHours = new CategoryTrackerEntity();
		LogDataTimeAgregator logDataMoinths = new LogDataTimeAgregator(configurationForMonths, timeAgregatorCalculator);
		LogDataTimeAgregator logDataWeeks = new LogDataTimeAgregator(configurationForWeeks, timeAgregatorCalculator);
		LogDataTimeAgregator logDataDays = new LogDataTimeAgregator(configurationForDays, timeAgregatorCalculator);
		LogDataSimpleTime simpleTimeMonths = new LogDataSimpleTime(configurationForMonths, simpleTimeCalculator, categoryTrackerEntityMonths);
		LogDataSimpleTime simpleTimeWeeks = new LogDataSimpleTime(configurationForWeeks, simpleTimeCalculator, categoryTrackerEntityWeeks);
		LogDataSimpleTime simpleTimeDays = new LogDataSimpleTime(configurationForDays, simpleTimeCalculator, categoryTrackerEntityDays);
		LogDataSimpleTime simpleTimeHours = new LogDataSimpleTime(configurationForHours, simpleTimeCalculator, categoryTrackerEntityHours);

		logAnalyzer.process(configurationForMonths, new ILogData[] { logDataMoinths, logDataWeeks, logDataDays, simpleTimeMonths, simpleTimeWeeks, simpleTimeDays, simpleTimeHours }, processingStatusEntity);

		CounterForDateAndResponseTimeEntity[] sortedByCountMonths = categoryTrackerEntityMonths.getSortedByCount();
		CounterForDateAndResponseTimeEntity[] sortedByCountWeeks = categoryTrackerEntityWeeks.getSortedByCount();
		CounterForDateAndResponseTimeEntity[] sortedByCountDays = categoryTrackerEntityDays.getSortedByCount();
		CounterForDateAndResponseTimeEntity[] sortedByCountHours = categoryTrackerEntityHours.getSortedByCount();
		generalStatisticToJSON.generate(configurationForMonths, sortedByCountMonths, "MonthsStatistic.json");
		generalStatisticToJSON.generate(configurationForWeeks, sortedByCountWeeks, "WeeksStatistic.json");
		generalStatisticToJSON.generate(configurationForDays, sortedByCountDays, "DaysStatistic.json");
		generalStatisticToJSON.generate(configurationForHours, sortedByCountHours, "HoursStatistic.json");
		generalStatisticToJSON.generateGeneralInfo(configurationForMonths, "GeneralStatisticConfiguration.json");

		processingStatusEntity.setInitilChartsAmountToProcess(2*sortedByCountMonths.length + 2*sortedByCountWeeks.length + 2*sortedByCountDays.length + sortedByCountHours.length);
		for (CounterForDateAndResponseTimeEntity counterForDateAndResponseTime : sortedByCountMonths) {
			multipleAxisChartRenderer.renderChart(configurationForMonths, processingStatusEntity, logDataMoinths, simpleTimeMonths, counterForDateAndResponseTime.getCategory());
			processingStatusEntity.decrementChartsAmountToProcess();
			multipleAxisChartRenderer.renderChartProbability(configurationForMonths, counterForDateAndResponseTime);
			processingStatusEntity.decrementChartsAmountToProcess();
		}
		for (CounterForDateAndResponseTimeEntity counterForDateAndResponseTime : sortedByCountWeeks) {
			multipleAxisChartRenderer.renderChart(configurationForWeeks, processingStatusEntity, logDataWeeks, simpleTimeWeeks, counterForDateAndResponseTime.getCategory());
			processingStatusEntity.decrementChartsAmountToProcess();
			multipleAxisChartRenderer.renderChartProbability(configurationForWeeks, counterForDateAndResponseTime);
			processingStatusEntity.decrementChartsAmountToProcess();
		}
		for (CounterForDateAndResponseTimeEntity counterForDateAndResponseTime : sortedByCountDays) {
			multipleAxisChartRenderer.renderChart(configurationForDays, processingStatusEntity, logDataDays, simpleTimeDays, counterForDateAndResponseTime.getCategory());
			processingStatusEntity.decrementChartsAmountToProcess();
			multipleAxisChartRenderer.renderChartProbability(configurationForDays, counterForDateAndResponseTime);
			processingStatusEntity.decrementChartsAmountToProcess();
		}
		for (CounterForDateAndResponseTimeEntity counterForDateAndResponseTime : sortedByCountHours) {
			multipleAxisChartRenderer.renderChart24Hours(configurationForHours, processingStatusEntity, simpleTimeHours, counterForDateAndResponseTime.getCategory());
			processingStatusEntity.decrementChartsAmountToProcess();
		}		
		
	}

}
